package net.quanter.shield.mybatis.page;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.ISelect;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import net.quanter.shield.common.dto.result.page.*;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 在分页时使用的工具辅助类
 *
 * @author 王老实
 * @since 1.3.12.RELEASE
 */
public class PageUtil {

    public static final String PAGE_NUM = "pageNum";
    public static final String PAGE_SIZE = "pageSize";

    public static final int DEFAULT_PAGE_NUM = 1;

    public static final int DEFAULT_PAGE_SIZE = 10;
    /**
     * 一个请求多个分页时所使用的线程变量
     */
    private final static ThreadLocal<Map<String, PageDTO>> THREAD_MAP = new ThreadLocal<>();
    private final static String DEFAULT_THREAD_NAME = PageUtil.class.getName();
    public static final PageDTO DEFAULT_PAGE_DTO = new PageDTO(DEFAULT_PAGE_SIZE);


    public static void set(Integer pageNum, Integer pageSize) {
        PageDTO page = new PageDTO(pageNum, pageSize);
        set(DEFAULT_THREAD_NAME, page);
    }

    public static void set(String name, Integer pageNum, Integer pageSize) {
        PageDTO page = new PageDTO(pageNum, pageSize);
        set(name, page);
    }

    public static void set(String name, PageDTO page) {
        Map<String, PageDTO> map = THREAD_MAP.get();
        if (map == null || !map.containsKey(name)) {
            map = new HashMap<>(8);
        }
        map.put(name, page);
        THREAD_MAP.set(map);
    }

    public static PageDTO get() {
        return get(DEFAULT_THREAD_NAME);
    }

    public static PageDTO get(String name) {
        if (THREAD_MAP.get() == null) {
            return null;
        }
        Map<String, PageDTO> map = THREAD_MAP.get();
        if (map == null || !map.containsKey(name)) {
            return null;
        }
        return map.get(name);
    }

    public static <T> Page<T> getPage() {
        return getPage(DEFAULT_THREAD_NAME);
    }

    public static <T> Page<T> getPage(String name) {
        if (THREAD_MAP.get() == null) {
            return new Page(DEFAULT_PAGE_DTO.getStartRow(), DEFAULT_PAGE_DTO.getPageSize());
        }
        Map<String, PageDTO> map = THREAD_MAP.get();
        if (map == null || !map.containsKey(name)) {
            return new Page(DEFAULT_PAGE_DTO.getStartRow(), DEFAULT_PAGE_DTO.getPageSize());
        }
        PageDTO pageDTO = map.get(name);
        return new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
    }

    public static void remove() {
        if (THREAD_MAP.get() != null) {
            THREAD_MAP.get().clear();
            THREAD_MAP.remove();
        }
    }

    public static <T extends Serializable> ListPageResultDTO<T> doSelectInfo(ISelect select) {
        PageDTO pageDTO = get();
        if (pageDTO == null) {
            pageDTO = DEFAULT_PAGE_DTO;
        }
        PageInfo<T> pageInfo = PageHelper
            .startPage(pageDTO.getPageNum(), pageDTO.getPageSize(), true, pageDTO.getReasonable(), pageDTO.getPageSizeZero())
            .doSelectPageInfo(select);
        return create(pageInfo);
    }

    public static <T extends Serializable> ListFullPageResultDTO<T> doSelectInfoFull(ISelect select) {
        PageDTO pageDTO = get();
        if (pageDTO == null) {
            pageDTO = DEFAULT_PAGE_DTO;
        }
        PageInfo<T> pageInfo = PageHelper
            .startPage(pageDTO.getPageNum(), pageDTO.getPageSize(), true, pageDTO.getReasonable(), pageDTO.getPageSizeZero())
            .doSelectPageInfo(select);
        return createFull(pageInfo);
    }

    protected static <T extends Serializable> ListPageResultDTO<T> create(PageInfo<T> pageInfo) {
        PageInfoDTO pageInfoDTO = new PageInfoDTO();
        pageInfoDTO.setPageNum(pageInfo.getPageNum());
        pageInfoDTO.setPageSize(pageInfo.getPageSize());
        pageInfoDTO.setTotal(pageInfo.getTotal());
        return new ListPageResultDTO<>(pageInfo.getList(), pageInfoDTO);
    }

    protected static <T extends Serializable> ListFullPageResultDTO<T> createFull(PageInfo<T> pageInfo) {
        FullPageInfoDTO pageInfoDTO = new FullPageInfoDTO();
        pageInfoDTO.setStartRow(pageInfo.getStartRow());
        pageInfoDTO.setPageSize(pageInfo.getPageSize());
        pageInfoDTO.setTotal(pageInfo.getTotal());
        pageInfoDTO.setSize(pageInfo.getSize());
        pageInfoDTO.setStartRow(pageInfo.getStartRow());
        pageInfoDTO.setEndRow(pageInfo.getEndRow());
        pageInfoDTO.setPages(pageInfo.getPages());
        pageInfoDTO.setPrePage(pageInfo.getPrePage());
        pageInfoDTO.setNextPage(pageInfo.getNextPage());
        pageInfoDTO.setFirstPage(pageInfo.isIsFirstPage());
        pageInfoDTO.setLastPage(pageInfo.isIsLastPage());
        pageInfoDTO.setHasPreviousPage(pageInfo.isHasPreviousPage());
        pageInfoDTO.setHasNextPage(pageInfo.isHasNextPage());
        pageInfoDTO.setNavigateFirstPage(pageInfo.getNavigateFirstPage());
        pageInfoDTO.setNavigateLastPage(pageInfo.getNavigateLastPage());
        pageInfoDTO.setNavigatepageNums(pageInfo.getNavigatepageNums());
        pageInfoDTO.setNavigatePages(pageInfo.getNextPage());
        return new ListFullPageResultDTO<>(pageInfo.getList(), pageInfoDTO);
    }

    public static <T extends Serializable> ListPageResultDTO<T> getListPageResult(IPage<T> page){
        PageInfoDTO pageInfoDTO = new PageInfoDTO();
        pageInfoDTO.setPageNum((int)page.getCurrent());
        pageInfoDTO.setPageSize((int)page.getSize());
        pageInfoDTO.setTotal(page.getTotal());
        return new ListPageResultDTO(page.getRecords(),pageInfoDTO);
    }
}
